////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                                                            //
//                                                         WNProject                                                          //
//                                                                                                                            //
//            This file is distributed under the BSD 2-Clause open source license. See License.txt for details.               //
//                                                                                                                            //
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#pragma once

#ifndef __WN_CONTAINERS_RESOURCE_POINTER_H__
#define __WN_CONTAINERS_RESOURCE_POINTER_H__

#include "WNCore/inc/WNPlatform.h"
#include "WNCore/inc/WNTypes.h"
#include "WNCore/inc/WNAssert.h"
#include "WNCore/inc/WNAtomic.h"
#include "WNMemory/inc/WNAllocation.h"

namespace WNContainers {
    template <typename Type>
    class WNResourcePointer {
    public:
        WNResourcePointer();
        WNResourcePointer(Type* _resource);
        
        WNResourcePointer(const WNResourcePointer& _resourcePointer);

        template<typename T2>
        WNResourcePointer(const WNResourcePointer<T2>& _resourcePointer);

        ~WNResourcePointer();

        Type* operator -> ();
        const Type* operator -> () const;
        Type& operator * ();
        operator bool() const;
        WNResourcePointer& operator= (const WNResourcePointer& _resourcePointer);
        
        template<typename T2>
        WNResourcePointer& operator= (const WNResourcePointer<T2>& _resourcePointer);

    private:
        template <typename T> friend class WNResourcePointer;
        WN_VOID RemoveRef();

    private:
        Type* mResource;
    };
    
    template <typename Type, typename Type2>
    WN_BOOL operator==(const WNResourcePointer<Type>& t1, const WNResourcePointer<Type2>& t2);

    template <typename Type>
    WNResourcePointer<Type> WNAllocateResource();

    template <typename Type, typename P1>
    WNResourcePointer<Type> WNAllocateResource1(P1 p);

    template <typename Type, typename P1, typename P2>
    WNResourcePointer<Type> WNAllocateResource2(P1 p, P2 p2);

    template <typename Type, typename P1, typename P2, typename P3>
    WNResourcePointer<Type> WNAllocateResource3(P1 p, P2 p2, P3 p3);

    template <typename Type, typename P1, typename P2, typename P3, typename P4>
    WNResourcePointer<Type> WNAllocateResource4(P1 p, P2 p2, P3 p3, P4 p4);

}

#include "WNContainers/inc/WNResourcePointer.inl"

#endif // __WN_CONTAINERS_RESOURCE_POINTER_H__